/**
@author		Jong Min, Lee
@date		  01/21/2014
@brief		viewer property class

copyright(c) Tae Young Soft. All right reserved. 2014
*/
#include "stdafx.h"
#include "Taurus_Viewer/ViewerProperty.h"

#include "Taurus_Common/IAppGlobalInstanceSet.h"
#include "Taurus_Common/IWorklistModule.h"
#include "Taurus_Util/Errors.h"
#include "Taurus_Viewer/Logger.h"
#include "Taurus_Viewer/ViewerPropertyParam.h"
#include "Taurus_Viewer/VGlobalInstanceSet.h"

CViewerProperty* CViewerProperty::m_pInstance = NULL;

CViewerProperty::CViewerProperty()
  : m_pPropertyDoc(NULL)
  , m_bNeedCommit(FALSE)
{}

CViewerProperty::~CViewerProperty()
{}

CViewerProperty* CViewerProperty::getInstance()
{
  if(m_pInstance == NULL)
    _TRY_ALLOC(m_pInstance, CViewerProperty);
  return m_pInstance;
}

DWORD CViewerProperty::setProperty(MSXML2::IXMLDOMDocument2Ptr pPropertyDoc)
{
  if(pPropertyDoc == NULL)
    return ERROR_INVALID_PARAMETER;

  //find viewer property node
  CString strXPath;
  strXPath.Format(_T("//%s"), VIEWER_PROPERTY_NAME);
  MSXML2::IXMLDOMNodePtr pPropertyNode = XmlFunc::SelectSingleNodeInXmlDoc(
    pPropertyDoc, strXPath);
  if(pPropertyNode == NULL)
  {
    TAURUS_VIEWER_ERROR("CViewerProperty::setProperty(): " <<
      "Can't find viewer property xml node.");
    return ERROR_VIEWER_PROPERTY_NOT_FOUND;
  }

  //convert property node to string
  CString strXml;
  try
  {
    BOOL fOk = XmlFunc::GetOuterXml(pPropertyNode, strXml);
    if(!fOk)
    {
      TAURUS_VIEWER_ERROR("CViewerProperty::setProperty(): " <<
        "Can't convert property xml node to string");
      return ERROR_XML_PARSER;
    }
  }
  catch(CMemoryException* e)
  {
    TAURUS_VIEWER_ERROR("CViewerProperty::setProperty(): " 
      << "Can't convert property xml node to string, "
      << "because property xml node is tool long.");
    e->Delete();
    return ERROR_NOT_ENOUGH_MEMORY;
  }

  destroy();

  //convert xml string to xml document
  m_pPropertyDoc = XmlFunc::LoadXmlDocString(strXml);
  if(m_pPropertyDoc == NULL)
  {
    TAURUS_VIEWER_ERROR("CViewerProperty::setProperty(): "
      << "Can't convert xml string to xml document");
    return ERROR_XML_PARSER;
  }

  return ERROR_SUCCESS;
}

MSXML2::IXMLDOMNodePtr CViewerProperty::getProperty(const TCHAR* pszXPath)
{
  if(pszXPath == nullptr || m_pPropertyDoc == nullptr)
    return NULL;

  MSXML2::IXMLDOMNodePtr pProperty = XmlFunc::SelectSingleNodeInXmlDoc(
    m_pPropertyDoc, pszXPath);
  if(pProperty == NULL)
    return NULL;

  CString strXml;
  try
  {
    BOOL fOk = XmlFunc::GetOuterXml(pProperty, strXml);
    if(!fOk)
    {
      TAURUS_VIEWER_ERROR("CViewerProperty::getProperty(): "
        << "Cant't convert " << pszXPath << " property xml node to string");
      return NULL;
    }
  }
  catch(CMemoryException* e)
  {
    TAURUS_VIEWER_ERROR("CViewerProperty::getProperty(): "
      << "Cant't convert " << pszXPath << " property xml node to string, "
      << "because property xml string is too long.");
    e->Delete();
    return NULL;
  }

  MSXML2::IXMLDOMDocument2Ptr pDoc = XmlFunc::LoadXmlDocString(strXml);
  if(pDoc == NULL)
  {
    TAURUS_VIEWER_ERROR("CViewerProperty::getProperty(): "
      << "Can't convert xml string to xml document");
    return NULL;
  }

  return XmlFunc::GetRoot(pDoc);
}

DWORD CViewerProperty::commit()
{
  if(m_pPropertyDoc == NULL)
    return ERROR_INIT_NEEDED;

  if(!m_bNeedCommit)
    return ERROR_SUCCESS;

  CViewerPropertyParam cParam;
  CString strPart = _T("USER_PROFILE");
  cParam.setParam(PARAM_USER_PROFILE_PART, (WPARAM)&strPart, NULL);
  CString strItem = _T("VIEWER_PROFILE");
  cParam.setParam(PARAM_USER_PROFILE_ITEM, (WPARAM)&strItem, NULL);
  CAdapt<MSXML2::IXMLDOMDocument2Ptr> cValue(m_pPropertyDoc);
  cParam.setParam(PARAM_USER_PROFILE_VALUE, (WPARAM)&cValue, NULL);

  CVGlobalInstanceSet* pVGSet = CVGlobalInstanceSet::getInstance();
  IAppGlobalInstanceSet* pAppGSet = pVGSet->getAppGlobalInstanceSet();
  IWorklistModule* pWorklist = pAppGSet->getWorklist();

  DWORD dwError = pWorklist->commitViewerProperty(&cParam);
  if(dwError != ERROR_SUCCESS)
    return dwError;

  m_bNeedCommit = FALSE;
  return ERROR_SUCCESS;
}

DWORD CViewerProperty::updateProperty(const TCHAR* pszParentName, 
                                      const TCHAR* pszName, 
                                      MSXML2::IXMLDOMNodePtr pPropertyNode)
{
  if(pszParentName == NULL || pszName == NULL || pPropertyNode == NULL)
    return ERROR_INVALID_PARAMETER;

  if(m_pPropertyDoc == NULL)
    return ERROR_INIT_NEEDED;

  //find parent node
  CString strXPath;
  strXPath.Format(_T("//%s"), pszParentName);
  MSXML2::IXMLDOMNodePtr pParentProperty = XmlFunc::SelectSingleNodeInXmlDoc(
    m_pPropertyDoc, strXPath);
  if(pParentProperty == NULL)
  {
    TAURUS_VIEWER_ERROR("CViewerProperty::updateProperty(): "
      <<"Can't find " << strXPath << " node.");
    return ERROR_INVALID_PARAMETER;
  }

  MSXML2::IXMLDOMNodePtr pCurrentProperty = XmlFunc::SelectSingleNodeInXmlNode(
    pPropertyNode, pszName);
  if(pCurrentProperty != NULL)
  {
    BOOL fOk = XmlFunc::Detach(pCurrentProperty);
    if(!fOk)
    {
      TAURUS_VIEWER_ERROR("CViewerProperty::updateProperty(): "
        << "Can't detach current property xml node.");
        return ERROR_XML_PARSER;
    }
  }

  MSXML2::IXMLDOMDocument2Ptr pTemp = XmlFunc::CreateXmlInstance();
  if(pTemp == NULL)
  {
    TAURUS_VIEWER_ERROR("CViewerProperty::updateProperty(): "
      << "Can't create xml instance.");
    return ERROR_XML_PARSER;
  }

  _TRY_BEGIN 
  pTemp->loadXML(pPropertyNode->xml);
  _CATCH_ALL
  TAURUS_VIEWER_ERROR("CViewerProperty::updateProperty(): "
    << "Can't load new property xml node");
  return ERROR_XML_PARSER;
  _CATCH_END

  MSXML2::IXMLDOMNodePtr pRoot = XmlFunc::GetRoot(pTemp);
  if(pRoot == NULL)
    return ERROR_XML_PARSER;

  BOOL fOk = XmlFunc::AttachChild(pParentProperty, pRoot);
  if(!fOk)
    return ERROR_XML_PARSER;

  m_bNeedCommit = TRUE;
  return ERROR_SUCCESS;
}

DWORD CViewerProperty::rollback()
{
  ///TODO(Jong Min, Lee)
  return ERROR_SUCCESS;
}

void CViewerProperty::destroy()
{
  if(m_bNeedCommit)
    commit();

  m_pPropertyDoc = NULL;
}








